﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Xml;
using umbraco.BusinessLogic;
using umbraco.IO;

namespace TheOutfield.UmbExt.DesktopMediaUploader
{
    public class Config
    {
        private const string SCHEMA_NAMESPACE = "urn:dmu-schema";

        private XmlDocument _configXml;

        #region Singleton

        private static Config _instance;

        public static Config Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Config();

                return _instance;
            }
        }

        private Config()
        {
            ParseConfig();
        }

        #endregion

        private void ParseConfig()
        {
            var configPath = HttpContext.Current.Server.MapPath("/config/desktopMediaUploader.config");

            if (File.Exists(configPath))
            {
                _configXml = new XmlDocument();
                XmlReader xmlReader = null;
                try
                {
                    // Read configfile with schema
                    // Get schema from assembly
                    Stream schemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("TheOutfield.UmbExt.DesktopMediaUploader.DesktopMediaUploader.xsd");

                    // XmlReader settings
                    XmlReaderSettings settings = new XmlReaderSettings();
                    if (schemaStream != null)
                    {
                        settings.ValidationType = ValidationType.Schema;
                        settings.Schemas.Add(SCHEMA_NAMESPACE, XmlReader.Create(schemaStream));
                        settings.ValidationEventHandler += settings_ValidationEventHandler;
                    }

                    // Create XmlReader
                    xmlReader = XmlReader.Create(configPath, settings);

                    // Read xml
                    _configXml.Load(xmlReader);
                }
                catch (XmlException)
                {
                    if (xmlReader != null)
                        xmlReader.Close();

                    Log.Add(LogTypes.Error, -1, "desktopMediaUploader.config invalid XML");
                }
            }
            else
            {
                Log.Add(LogTypes.Error, -1, "desktopMediaUploader.config not found");
            }
        }

        [Obsolete]
        public IMediaFactory GetMediaFactory(int parentNodeId, HttpPostedFile postedFile, User user)
        {
            return GetMediaFactory(parentNodeId, new PostedMediaFile(postedFile), user);
        }

        public IMediaFactory GetMediaFactory(int parentNodeId, PostedMediaFile uploadFile, User user)
        {
            // Get extension
            string ext = uploadFile.FileName.Substring(uploadFile.FileName.LastIndexOf(".") + 1).ToLower();

            if (_configXml != null)
            {
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(_configXml.NameTable);
                nsmgr.AddNamespace("dmu", SCHEMA_NAMESPACE);

                // Fetch mediaFactories based on extension
                XmlNodeList factoryNodes =
                    _configXml.SelectNodes("/dmu:desktopMediaUploader/dmu:mediaFactory [dmu:extensions/dmu:ext/text() = '" + ext + "']", nsmgr);

                // If no factory select default factory
                if (factoryNodes == null || factoryNodes.Count == 0)
                    factoryNodes = _configXml.SelectNodes("/dmu:desktopMediaUploader/dmu:mediaFactory [dmu:extensions/dmu:ext/text()='*'] [1]", nsmgr);

                if (factoryNodes != null && factoryNodes.Count > 0)
                {
                    foreach (XmlNode factoryNode in factoryNodes)
                    {
                        // Create appropriate IMediaFactory instance
                        string assemblyName = factoryNode.SelectSingleNode("@assembly", nsmgr).Value;
                        string typeName = factoryNode.SelectSingleNode("@type", nsmgr).Value;

                        // Build full qualified type string
                        string fullQualifiedType = string.Empty;

                        XmlNode namespaceNode = factoryNode.SelectSingleNode("@namespace", nsmgr);
						if (namespaceNode != null)
							fullQualifiedType = namespaceNode.Value + ".";

                        fullQualifiedType += typeName + "," + assemblyName;

                        // Create type from full qualified string
                        Type type = Type.GetType(fullQualifiedType);

                        // Create instance type
						IMediaFactory mediaFactory = Activator.CreateInstance(type) as IMediaFactory;
                        if (mediaFactory != null && mediaFactory.CanHandleMedia(parentNodeId, uploadFile, user))
							return mediaFactory;
                    }
                }
            }

            // No config
            // No matching extension
            // No default media factory configured

            // Use DefaultFileMediaFactory
            return new UmbracoFileMediaFactory();
        }

        protected void settings_ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs e)
        {
            XmlReader xmlReader = (XmlReader)sender;
            xmlReader.Close();

            Log.Add(LogTypes.Error, -1, "Invalid xml format in desktopMediaUploader.config: " + e.Message);
        }
    }
}